<?php


namespace App\Services;
use Carbon\Carbon;
use Facade\Ignition\Tabs\Tab;
use Illuminate\Database\Schema\Blueprint;
use App\Services\DBAPP as DB;
use App\Models\Table as TableModel;
use App\Models\Column as ColumnModel;

class Table
{
    private static $error;
    public static function error() {
        return self::$error;
    }

    public static function create($dbId, $title, $name, $columns) {
        $table = $name;
        if (DB::schema()->hasTable($table)) {
            self::$error = '表['.$table.']已经存在';
            return false;
        }

        $columns = self::column_format($columns);
        if (!$columns) {
            return false;
        }

        // 存储表信息
        $tableInfo = TableModel::create([
            'db_id' => $dbId,
            'name'  => $name,
            'title' => $title
        ]);

        // 存储字段信息
        $time = Carbon::now();
        foreach($columns as $key => &$column) {
            $column['sort'] = $key;
            $column['table_id'] = $tableInfo->id;
            $column['created_at'] = $time;
            $column['updated_at'] = $time;
        }
        ColumnModel::insert($columns);

        // 检查表格
        DB::schema()->create($table, function (Blueprint $table) use ($columns) {
            $table->id();
            foreach ($columns as $column) {
                $type   = $column['type'];
                $len    = $column['length'];
                $name   = $column['name'];
                $title  = $column['title'];
                $float  = $column['floatnum'];

                /*switch ($type) {
                    case 'float':   $row = $table->float($name, $len, $column['floatnum']); break;
                    case 'string':  $row = $table->string($name, $len); break;
                    case 'file':    $row = $table->string($name, 200); break;
                    case 'textarea':;
                    case 'text':    $row = $table->text($name); break;
                    default:        $row = $table->$type($name);
                }

                $row->comment($column['title']);    // 注释
                $row->nullable();                   // 允许null
                */
                self::addNewColumn($table, $type, $name, $title, $len, $float);
            }
            $table->timestamps();
        });

        return $tableInfo;
    }

    public static function drop($tableId) {
        $tableInfo  = TableModel::find($tableId);
        $schema     = DB::schema();
        $tableName  = $tableInfo->name;
        if ($schema->hasTable($tableName)) {
            $schema->drop($tableName);

            // 删除字段
            ColumnModel::where('table_id', $tableId)->delete();
        }
        $tableInfo->delete();
    }

    public static function dropColum($columnId) {
        $column = ColumnModel::find($columnId);
        $table  = TableModel::find($column->table_id);
        $columnName = $column->name;
        $column->delete();
        DBAPP::schema()->table($table->name, function(Blueprint $table) use ($columnName) {
           $table->dropColumn($columnName);
        });
    }

    /**
     * 修改表
     * @param $id int 表ID
     * @param $name string
     * @param $title string
     * @param $columns array
     */
    public static function update($tableId, $name, $title, $columns) {
        $schema = DB::schema();
        // 有三种类型 add, change, rename

        $columns = self::column_format($columns);
        if (!$columns) {
            return false;
        }

        // 查看是否修改表名
        $oldTable = TableModel::find($tableId);
        if ($oldTable->name != $name) {
            $schema->rename($oldTable->name, $name);
        }

        if ($oldTable->name != $name || $oldTable->title != $title) {
            $oldTable->title = $title;
            $oldTable->name = $name;
            $oldTable->save();
        }

        $schema->table($name, function (Blueprint $table) use ($columns, $tableId) {

            $after = 'id';
            foreach ($columns as $key => $column) {

                $type   = $column['type'];
                $len    = $column['length'];
                $name   = $column['name'];
                $title  = $column['title'];
                $float  = $column['floatnum'];
                $column['sort'] = $key;

                if ($column['id'] == 0) {   // 新增

                    // if ($type == 'string') {
                    //     $table->string($name, $len)->comment($title);
                    // } else {
                    //     $table->$type($name)->comment($title);
                    // }

                    self::addNewColumn($table, $type, $name, $title, $len, $float);
                    $column['table_id'] = $tableId;
                    ColumnModel::create($column);
                    continue;
                } else { // 重命名

                    $oldColumn = ColumnModel::find($column['id']);
                    if ($oldColumn->name != $column['name']) {

                        $table->renameColumn($oldColumn->name, $column['name']);

                    } else {  // 修改 类型，长度，主键
                        switch ($type) {
                            case 'string':;
                            case 'file':
                                $row = $table->string($name,$len);  break;
                            case 'article':;
                            case 'textarea':
                                $row = $table->text($name); break;
                            default:
                                $row = $table->$type($name);
                        }

                        $row->after($after)->change();
                    }
                }
                unset($column['created_at']);
                unset($column['updated_at']);
                ColumnModel::where('id', $column['id'])->update($column);
            }
        });
        return true;
    }

    static function addNewColumn(&$table, $type, $name, $title, $len, $floatNum) {
        switch ($type) {
            case 'float':   $row = $table->float($name, $len, $floatNum); break;
            case 'string':  $row = $table->string($name, $len); break;
            case 'file':    $row = $table->string($name, 200); break;
            case 'textarea':;
            case 'text':    $row = $table->text($name); break;
            default:        $row = $table->$type($name);
        }

        $row->comment($title);    // 注释
        $row->nullable();                   // 允许null
    }

    const COLUMN_TYPES = ['integer', 'string', 'textarea', 'date', 'datetime', 'text', 'float', 'file', 'text'];
    /**
     * 检查字段 必须包含字段【name | type | length | title 】
     * @param array $columns
     * @return bool|array
     */
    static function column_format(array $columns) {
        $options = ['name', 'type', 'length', 'title'];
        foreach ($columns as &$column) {

            /*1.检查属性是否都齐全*/
            foreach ($options as $option) {
                if (!isset($column[$option])) {
                    self::$error = '字段缺少'.$option.'属性';
                    return false;
                }
            }

            /*2.检查类型是否在规定范围内*/
            if (!in_array($column['type'], self::COLUMN_TYPES)) {
                self::$error = '不存在的字段类型:' . $column['type'];
                return false;
            }

            /*3.检查小数位*/
            if ($column['type'] == 'float') {
                $column['floatnum'] = $column['floatnum'] ?? 2;
            } else {
                $column['floatnum'] = 0;
            }
        }

        return $columns;
    }
}
